---
import Layout from '~layouts/VanillaDemo.astro';
import {title} from './_instanced-quads.json';
---

<Layout title={title}>
  <canvas id="canvas-container" resize-to="window"></canvas>
</Layout>

<style>
  body {
    height: 100vh;
    overflow-y: hidden;
  }
  body {
    background-color: #391e39;
    background: radial-gradient(circle, rgba(189, 70, 98, 1) 0%, rgba(37, 4, 73, 1) 100%);
  }
</style>

<script>
  import {InstancedVertexObjectGeometry, VertexObjects, type VO} from '@spearwolf/twopoint5d';
  import {DoubleSide, RawShaderMaterial} from 'three';
  import fragmentShaderSource from '~demos/shaders/instanced-quads.frag?url';
  import vertexShaderSource from '~demos/shaders/instanced-quads.vert?url';
  import {PerspectiveOrbitDemo} from '~demos/utils/PerspectiveOrbitDemo';
  import loadShaderSource from '~demos/utils/loadShaderSource';

  interface BaseQuad extends VO {
    setPosition(position: [number, number, number, number, number, number, number, number, number, number, number, number]): void;
  }

  class BaseQuad {
    make(width = 0.5, height = 0.5) {
      this.setPosition([-width, -height, 0, -width, +height, 0, +width, +height, 0, +width, -height, 0]);
    }
  }

  const BaseQuadDescriptor = {
    vertexCount: 4,
    indices: [0, 2, 1, 0, 3, 2],

    attributes: {
      position: {components: ['x', 'y', 'z']},
    },

    basePrototype: BaseQuad.prototype,
  };

  interface InstancedQuad extends VO {
    width: number;
    height: number;

    setInstancePosition: (position: [number, number]) => void;
  }

  const InstancedQuadDescriptor = {
    meshCount: 1,

    attributes: {
      quadSize: {components: ['width', 'height']},
      instancePosition: {components: ['x', 'y', 'z']},
    },
  };

  async function makeMesh(rows: number, columns: number, size: number, offset: number) {
    const capacity = rows * columns;

    const geometry = new InstancedVertexObjectGeometry<InstancedQuad, BaseQuad>(
      InstancedQuadDescriptor,
      capacity,
      BaseQuadDescriptor,
    );

    geometry.basePool.createVO().make();

    for (let y = 0; y < rows; y++) {
      for (let x = 0; x < columns; x++) {
        const cross = geometry.instancedPool.createVO();
        cross.width = 1.0 + Math.random() * (size - 1.0);
        cross.height = 1.0 + Math.random() * (size - 1.0);
        cross.setInstancePosition([
          x * size * offset - ((columns - 1) * size * offset) / 2,
          y * size * offset - ((rows - 1) * size * offset) / 2,
        ]);
      }
    }

    const material = new RawShaderMaterial({
      vertexShader: await loadShaderSource(vertexShaderSource),
      fragmentShader: await loadShaderSource(fragmentShaderSource),
      transparent: true,
      side: DoubleSide,
    });

    const mesh = new VertexObjects(geometry, material);
    mesh.name = 'InstancedQuadsMesh';

    return mesh;
  }

  const demo = new PerspectiveOrbitDemo(document.getElementById('canvas-container'));

  await demo.start(async () => {
    demo.scene.add(await makeMesh(10, 20, 3.2, 1.2));
  });

  console.log('InstancedQuadsMesh', demo.scene.children[0]);
</script>
